/**
 * bmpHandler.h
 *
 * @brief gestisce in modo semplice una bitmap
 *
 *  Created on: May 21, 2013
 *      Author: koldar
 */

#ifndef BMPTOOLS_H_
#define BMPTOOLS_H_

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <stdbool.h>

/**rappresenta un colore di tipo RGB
 *
 */
typedef struct RGB {
	/**indica il canale rosso. i valori accettati sono [0-255].*/
	unsigned char r;
	/**indica il canale verde. i valori accettati sono [0-255].*/
	unsigned char g;
	/**indica il canale blu. i valori accettati sono [0-255].*/
	unsigned char b;
} RGB;

#define COLOR_RED			(RGB){255,0,0}
#define COLOR_DARK_RED		(RGB){100,0,0}
#define COLOR_ORANGE		(RGB){175,95,0}
#define COLOR_DARK_ORANGE	(RGB){125,40,0}
#define COLOR_YELLOW		(RGB){175,175,0}
#define COLOR_DARK_YELLOW	(RGB){75,75,0}
#define COLOR_GREEN			(RGB){0,255,0}
#define COLOR_DARK_GREEN	(RGB){0,100,0}
#define COLOR_CIAN			(RGB){0,175,175}
#define COLOR_DARK_CIAN		(RGB){0,75,75}
#define COLOR_BLUE			(RGB){0,0,255}
#define COLOR_DARK_BLUE		(RGB){0,0,100}
#define COLOR_VIOLET		(RGB){175,0,175}
#define COLOR_DARK_VIOLET	(RGB){75,0,75}
#define COLOR_GREY			(RGB){175,175,175}
#define COLOR_DARK_GREY		(RGB){75,75,75}
#define COLOR_BLACK			(RGB){0,0,0}
#define COLOR_WHITE			(RGB){255,255,255}


/**rappresenta la struttura principale per la semplice gestione di un'immagine. Inizializzarla tramite la funzione initImage().
 * Questa struttura non e' altro che una matrice di RGB elementi (ossia di pixels). E' possibile accederci in modo semplice tramite i metodi:
 *  \li setPixelInImage
 *  \li getRGB
 *
 */
typedef struct Image{
	/**la lunghezza della bitmap*/
	int width;
	/**l'altezza della bitmap*/
	int height;
	/**una matrice di pixel rappresentante i dati della bitmap*/
	RGB** map;
} Image;

/**un puntatore ad un'immagine. Utile per passare come riferimento l'immagine stessa evitando quindi di copiare questa enorme
 * struttura*/
typedef Image* Pimage;
/**
 *
 */
typedef RGB* PRGB;

/**costruisce un'immagine in memoria. Controllare sempre w e h poiche' questa struttura occupa molta memoria.
 * \pre
 *  \li w positivo non nullo
 *  \li h positivo non nullo
 *  \li un po' di memoria libera disponibile
 *
 * @param w la lunghezza  (in pixel) della bitmap
 * @param h l'altezza (in pixel) della bitmap
 * @return un puntatore ad un'immagine in memoria
 */
Pimage initImage(int w,int h);

/**libera la memoria occupata da img
 *
 * @param img l'immagine da deallocare
 */
void freeImage(Pimage img);

/**costruisce un'istanza di un colore di un pixel. Utile per assegnare un colore ad un pixel. Questa funzione
 * e' spesso utilizzata in setPixelInImage()
 *
 * @param r il canale rosso del colore
 * @param g il canale verde del colore
 * @param b il canale blu del colore
 * @return una struttura RGB rappresentante un colore
 */
RGB getRGB(unsigned char r,unsigned char g,unsigned char b);

/**stampa su f una rappresentazione umana del pixel RGB
 *
 * \pre
 *  \li f aperto in scrittura
 *  \li f non NULL
 *  \li rgb non NULL
 * \post
 * 	\li file f modificato
 *
 *
 * @param f il file su cui stampare
 * @param rgb oggetto da stampare sul file f
 */
void printRGB(FILE* f,RGB rgb);

/**determina se due pixel sono identici
 *
 * @param color1 il colore del primo pixel
 * @param color2 il colore del secondo pixel
 * @return TRUE se ogni campo delle due strutture RGB coincide, FALSE altrimenti
 */
bool equalsRGB(RGB color1,RGB color2);

/**imposta il colore pixel all'interno dell'immagine al valore rgb
 * \pre
 *  \li img non NULL
 *  \li x positivo (o nullo) e minore stretto del campo width di img
 *  \li y positivo (o nullo) e minore stretto del campo height di img
 *  \li RGB inizializzato correttamente
 * \post
 *  all'interno dell'immagine img, nel pixel di coordinate (x;y) e' contenuto il colore rgb
 *
 * @param img l'immagine da modificare
 * @param x la coodinata x (lunghezza) del pixel. 0 indica il lato sinistro dell'immagine
 * @param y la coordinata y (altezza) del pixel. 0 indica il lato in alto dell'immagine
 * @param rgb
 */
void setPixelInImage(Pimage img,int x,int y,RGB rgb);

/**imposta il colore pixel all'interno dell'immagine al valore rgb
 * \pre
 *  \li img non NULL
 *  \li x positivo (o nullo) e minore stretto del campo width di img
 *  \li y positivo (o nullo) e minore stretto del campo height di img
 *  \li RGB inizializzato correttamente
 * \post
 *  all'interno dell'immagine img, nel pixel di coordinate (x;y) e' contenuto il colore rgb
 *
 * @param img l'immagine da modificare
 * @param x la coodinata x (lunghezza) del pixel. 0 indica il lato sinistro dell'immagine
 * @param y la coordinata y (altezza) del pixel. 0 indica il lato in alto dell'immagine
 * @param rgb
 */
void updatePixelInImage(Pimage img,int x,int y,RGB rgb);

/**scrive all'interno di un file l'header della bitmap. Questa operazione e' necessaria affinche' il file venga visto dal computer
 * proprio come una bitmap. E' inoltre importante, quando si vorra' inserire una Image all'interno del file, che essa abbia come
 * altezza il valore M e come lunghezza il valore N
 *
 * \pre
 *  \li f aperto in modalita' di scrittura (fopen(file,"w")) non NULL
 *  \li M strettamente positivo
 *  \li N strettamente positivo
 * \post
 *  \li all'interno del file f e' scritto un semplicissimo header (che non supporta le funzionalita' avanzate della bitmap, come per esempio
 *  la compressione, l'alpha channel o le palettes) compatbile con una Image di width=N e height=M
 *
 * @param f il file che conterra' la bitmap
 * @param M l'altezza della bitmap
 * @param N la lunghezza della bitmap
 */
void writeHeaderInFile(FILE* f,int M,int N);

/**scrive all'interno di un file l'immagine scelta
 *
 * \pre
 *  \li img non NULL e inizializzato correttamente (trmaite initImage() )
 *  \li bmp non NULL, aperto in scrittura (fopen(f,"w");)
 *  \li la funzione writeHeaderInFile deve essere gia' stata creata
 * \post
 *  all'interno del file bmpfile e' contenuta una struttura che puo' essere interpretata come una bitmap
 *
 * @param img
 * @param bmpfile
 */
void applyImageToFile(Pimage img, FILE* bmpfile);

/**riempie tutta l'immagine passata come parametro di un unico colore
 *
 * \pre
 *  \li img non NULL
 *  \li color inizializzato correttamente
 * \post
 *  ogni pixel contenuto nell'immagine img ha come colore quello nel parametro color
 *
 * @param img l'immagine da riempire
 * @param color il colore con cui riempire l'intera immagine
 */
void fillColor(Pimage img,RGB color);

/** traccia una linea dalle coordinate (fromx; fromy) alle cooridnate (tox; toy) di ampiezza radius e colore color
 *
 * \pre
 *  \li img non NULL
 *  \li fromx appartenente a [0;W[
 *  \li fromy appartiene a [0;H[
 *  \li tox appartiene a [0;W[
 *  \li toy appartiene a [0;H[
 *  \li radius positivo o nullo
 * \post
 *  su img viene tracciata una linea
 *
 * @param img l'immagine su cui tracciare la linea
 * @param fromx l'ascissa del primo estremo della linea
 * @param fromy l'ordinata del primo estremo della linea
 * @param tox l'ascissa del secondo estremo della linea
 * @param toy l'ordinata del secondo estremo della linea
 * @param radius il raggio della linea da tracciare. 0 per la linea piu' sottile possibile
 * @param color il colore con cui tracciare la linea
 */
void drawLine(Pimage img,int fromx,int fromy, int tox, int toy, int radius, RGB color);


#endif /* BMPTOOLS_H_ */
